#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include "base.h"

int main(int argc, char const *argv[])
{
    if(argc!=3){
        printf("usage:%s <ip> <port>\n",argv[0]);
        return -1;
    }
    //创建socket
    int sockfd = socket(AF_INET,SOCK_STREAM,0); //ipv4 tcp
    if(sockfd<0){
        perror("socket err");
        return -1;
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(argv[2]));
    addr.sin_addr.s_addr = inet_addr(argv[1]);

    socklen_t addrlen = sizeof(addr);
    //连接
    if(connect(sockfd,(struct sockaddr*)&addr,addrlen)<0){
        perror("connect err");
        return -1;
    }
    printf("connect success\n");

    char filepath[32] = "";
    printf("请输入要下载的文件路径:\n");
    
    scanf("%s",filepath);
    //发送文件请求
    struct C2S_filename requst;
    requst.type = 1;
    strcpy(requst.filename,filepath);
    
    char buffer[256] = {0};
    int length = serialize_filename(buffer,&requst);
    char* buftosend = addlength(buffer,length);
    length+=sizeof(int);
    send(sockfd,buftosend,length,0);
    free_buftosend(&buftosend);

    length = recv_header(sockfd);
    //接受消息体
    recv(sockfd,buffer,length,0);

    struct S2C_fileinfo info;
    unserialize_fileinfo(&info,buffer);
    if(info.size == 0){
        printf("文件不存在!\n");
        close(sockfd);
        return -1;
    }
    printf("该文件大小:%ld字节\n",info.size);
    char newfile[32] = "";
    printf("输入下载文件存放的位置(带上文件名):\n");
    scanf("%s",newfile);

    int fd = open(newfile,O_CREAT|O_TRUNC|O_WRONLY,0666);
    if(fd<0){
        perror("open err");
        close(sockfd);
        return -1;
    }
    int n = info.size/BLOCK_SIZE +((info.size%BLOCK_SIZE>0) ? 1 : 0);
    
    struct C2S_loadinfo loadinfo;
    loadinfo.type = 3;
    loadinfo.offset = 0;
    strcpy(loadinfo.filepath,filepath);
    loadinfo.block_size = BLOCK_SIZE;
    for(int i=0;i<n;i++){
        memset(buffer,0,sizeof(buffer));
        //请求发送文件块
        length = serialize_loadinfo(buffer,&loadinfo);
        buftosend = addlength(buffer,length);
        length+=sizeof(int);
        send(sockfd,buftosend,length,0);
        free_buftosend(&buftosend);
        
        //接受文件块
        struct S2C_file_block block;
        length = recv_header(sockfd);
        //接受消息体
        memset(buffer,0,sizeof(buffer));
        recv(sockfd,buffer,length,0);
        printf("成功接受第%d个文件块\n",i+1);
        int len_content = unserialize_fileblock(&block,buffer);
        lseek(fd,block.offset,SEEK_SET);
        length = write(fd,block.content,len_content);
        loadinfo.offset+=length;
    }

    //关闭文件
    close(fd);
    close(sockfd);
    return 0;
}
